home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #4 / Amiga Plus CD - 2000 - No. 4.iso / Tools / Dev / Orbit_SRC / ac3d.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-27  |  26.7 KB  |  1,391 lines

  1. /*
  2.     Amiga port by Oliver Gantert
  3.  
  4.     27.04.2000 - fixed some compiler warnings
  5. */
  6. /*
  7.  
  8. ORBIT, a freeware space combat simulator
  9. Copyright (C) 1999  Steve Belczyk <steve1@genesis.nred.ma.us>
  10.  
  11. This program is free software; you can redistribute it and/or
  12. modify it under the terms of the GNU General Public License
  13. as published by the Free Software Foundation; either version 2
  14. of the License, or (at your option) any later version.
  15.  
  16. This program is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. GNU General Public License for more details.
  20.  
  21. You should have received a copy of the GNU General Public License
  22. along with this program; if not, write to the Free Software
  23. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  24.  
  25. */
  26.  
  27. #include "orbit.h"
  28.  
  29. /*
  30.  *  Stuff to load AC3D files
  31.  *
  32.  *  Most of this is based on ac-to-gl, by Steve Baker <sjbaker1@airmail.net>
  33.  */
  34.  
  35. int DoMaterial (char *s);
  36. int DoObject (char *s);
  37. int DoACName (char *s);
  38. int DoData (char *s);
  39. int DoTexture (char *s);
  40. int DoTexrep (char *s);
  41. int DoRot (char *s);
  42. int DoLoc (char *s);
  43. int DoUrl (char *s);
  44. int DoNumvert (char *s);
  45. int DoNumsurf (char *s);
  46. int DoSurf (char *s);
  47. int DoMat (char *s);
  48. int DoRefs (char *s);
  49. int DoKids (char *s);
  50.  
  51. int DoObjWorld (char *s);
  52. int DoObjPoly (char *s);
  53. int DoObjGroup (char *s);
  54. void SkipSpaces (char **s);
  55. void SkipQuotes (char **s);
  56. void RemoveQuotes (char *s);
  57. void load_sgi_texture (char *s);
  58.  
  59. #define MAX_TEXTURES 1000    /* This *ought* to be enough! */
  60. char *texture_fnames [MAX_TEXTURES];
  61.  
  62. int acsmooth;  /* Smooth surface? */
  63. int acsurfpass;  /* Pass through surface */
  64. #define PASS_NORMAL (0) /* Get normals */
  65. #define PASS_RENDER (1) /* Render */
  66.  
  67. struct
  68. {
  69.   int id;   /* Texture id */
  70.   char name[64]; /* Name */
  71. }
  72. tex[MAX_TEXTURES];
  73. int ntex;
  74.  
  75. struct ACVertex
  76. {
  77.   float v[3];     /* Vertex coords */
  78.   float normal[3]; /* Normal */
  79.   float n;        /* Number of normals to average */
  80. }
  81. *vtab;
  82.  
  83. int num_materials = 0;
  84. int num_textures = 0;
  85. int nv;   /* Number of vertices in vtab */
  86.  
  87. int last_flags = -1;
  88. int last_mat;
  89. int last_num_kids = -1;
  90. int current_flags = -1;
  91. int texture_enabled = 0;
  92. int need_texture = 0;
  93. int firsttime2;
  94.  
  95. #define PARSE_CONT   0
  96. #define PARSE_POP    1
  97.  
  98. int matlist[1024];
  99. int modelnum;
  100. FILE *acfd;
  101.  
  102. struct Tag
  103. {
  104.   char *token;
  105.   int (*func) (char *s);
  106. }
  107. ;
  108.  
  109. struct Tag top_tags [] =
  110. {
  111.   {
  112. "MATERIAL", DoMaterial}
  113.   ,
  114.   {
  115. "OBJECT"  , DoObject  }
  116.   ,
  117. }
  118. ;
  119.  
  120. void InitTextures()
  121. {
  122.   int t;
  123.  
  124.   for (t=0; t<MAX_TEXTURES; t++)
  125.   {
  126.     tex[t].id = (-1);
  127.     tex[t].name[0] = 0;
  128.   }
  129.  
  130.   ntex = 0;
  131. }
  132.  
  133. int LoadAC3D (char *name)
  134. {
  135.   char buffer[1024], *s, fn[128];
  136.   int firsttime, m;
  137.  
  138.   /* See if it's already loaded */
  139.   for (m=0; m<NMODELS; m++)
  140.   {
  141.     if (!strcmp (model[m].name, name)) return (m);
  142.   }
  143.  
  144.   Log ("LoadAC3D: Loading model %s", name);
  145.  
  146.   /* Find an unused model index */
  147.   m = modelnum = FindModel();
  148.   strcpy (model[m].name, name);
  149.   model[m].in_use = 1;
  150.  
  151.   /* Init bounding box */
  152.   model[m].lobound[0] = model[m].lobound[1] = model[m].lobound[2] = 0.0;
  153.   model[m].hibound[0] = model[m].hibound[1] = model[m].hibound[2] = 0.0;
  154.  
  155.   /* Get a list id */
  156.   model[m].list = glGenLists (1);
  157.  
  158.   /* Construct file name */
  159.   sprintf (fn, "models/%s", name);
  160.  
  161.   /* Open it */
  162.   if (NULL == (acfd = fopen (fn, "rt")))
  163.   {
  164.     Log ("LoadAC3D: Can't open %s, giving up!", fn);
  165.     return (-1);
  166.   }
  167.  
  168.   firsttime = 1;
  169.   firsttime2 = 1;
  170.  
  171.   num_materials = 0;
  172.   num_textures = 0;
  173.   vtab = NULL;
  174.   last_flags = -1 ;
  175.   last_num_kids = -1 ;
  176.   current_flags = -1 ;
  177.   texture_enabled = 0;
  178.   need_texture = 0;
  179.   last_mat = -1;
  180.  
  181.   /* Look for and define textures */
  182.   ScanForTextures();
  183.  
  184.   while (fgets (buffer, 1024, acfd) != NULL)
  185.   {
  186.     s = buffer ;
  187.  
  188.     /* Skip leading whitespace */
  189.     SkipSpaces (&s);
  190.  
  191.     /* Skip blank lines and comments */
  192.     if ( *s < ' ' && *s != '\t' ) continue;
  193.     if ( *s == '#' || *s == ';' ) continue;
  194.  
  195.     if (firsttime)
  196.     {
  197.       firsttime = 0;
  198.  
  199.       if (strncmp (s, "AC3D", 4) != 0)
  200.       {
  201.         Log ("LoadAC3d: %s is not an AC3D format file", fn);
  202.         return (-1);
  203.       }
  204.     }
  205.     else
  206.     {
  207.       Search (top_tags, s);
  208.     }
  209.   }
  210.  
  211.   glShadeModel (GL_FLAT);
  212.   glEndList();
  213.   fclose (acfd);
  214.  
  215.   Log ("LoadAC3D: Lo bounds: %lf %lf %lf", model[m].lobound[0],
  216.   model[m].lobound[1], model[m].lobound[2]);
  217.   Log ("LoadAC3D: Hi bounds: %lf %lf %lf", model[m].hibound[0],
  218.   model[m].hibound[1], model[m].hibound[2]);
  219.  
  220.   /* All is well */
  221.   return m;
  222. }
  223.  
  224. void ScanForTextures()
  225. /*
  226.  *  Look through the AC3D file for all "texture" lines
  227.  */
  228. {
  229.   char buf[1024], fn[256];
  230.  
  231.   /* Look for "texture" lines */
  232.   while (NULL != fgets (buf, 1024, acfd))
  233.   {
  234.     if (1 == sscanf (buf, "texture %s", fn))
  235.     {
  236.       RemoveQuotes (fn);
  237.       LoadTexture (fn);
  238.     }
  239.   }
  240.  
  241.   /* Rewind the file */
  242.   fseek (acfd, 0, SEEK_SET);
  243. }
  244.  
  245. void LoadTexture (char *s)
  246. /*
  247.  *  Load a texture file
  248.  */
  249. {
  250.   char fn[256];
  251.  
  252.   Log ("LoadTexture: Loading texture %s", s);
  253.  
  254.   /* Construct file name */
  255.   sprintf (fn, "models/%s", s);
  256.  
  257.   /* Get a texture id */
  258.   glGenTextures (1, &tex[ntex].id);
  259.   strcpy (tex[ntex].name, s);
  260.  
  261.   /* Define the texture */
  262.   glBindTexture (GL_TEXTURE_2D, tex[ntex].id);
  263.   glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
  264.   load_sgi_texture (fn);
  265.   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  266.   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  267.   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  268.   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  269.  
  270.   ntex++;
  271. }
  272.  
  273. void ACNormalize (float *v)
  274. {
  275.   float mag;
  276.  
  277.   mag = sqrt (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  278.  
  279.   if (mag == 0.0f)
  280.   {
  281.     v[0] = v[1] = 0.0f;
  282.     v[2] = 1.0f;
  283.     return;
  284.   }
  285.  
  286.   v[0] /= mag;
  287.   v[1] /= mag;
  288.   v[2] /= mag;
  289. }
  290.  
  291. void CrossProduct (float *dst, float *a, float *b)
  292. {
  293.   dst[0] = a[1] * b[2] - a[2] * b[1];
  294.   dst[1] = a[2] * b[0] - a[0] * b[2];
  295.   dst[2] = a[0] * b[1] - a[1] * b[0];
  296. }
  297.  
  298. void MakeNormal (float *dst, float *a, float *b, float *c)
  299. {
  300.   float ab[3];
  301.   float ac[3];
  302.  
  303.   ab[0] = b[0] - a[0];
  304.   ab[1] = b[1] - a[1];
  305.   ab[2] = b[2] - a[2];
  306.   ACNormalize (ab);
  307.  
  308.   ac[0] = c[0] - a[0];
  309.   ac[1] = c[1] - a[1];
  310.   ac[2] = c[2] - a[2];
  311.   ACNormalize (ac);
  312.  
  313.   CrossProduct (dst, ab, ac);
  314.   ACNormalize (dst);
  315. }
  316.  
  317. void SkipSpaces (char **s)
  318. {
  319.   while (**s == ' ' || **s == '\t') (*s)++;
  320. }
  321.  
  322. void SkipQuotes (char **s)
  323. {
  324.   char *t;
  325.  
  326.   SkipSpaces (s);
  327.  
  328.   if (**s == '\"')
  329.   {
  330.     (*s)++;
  331.     t = *s;
  332.     while (*t != '\0' && *t != '\"') t++;
  333.  
  334.     if ( *t != '\"' )
  335.     Log ("SkipQuotes: Mismatched double-quote in '%s'\n", *s);
  336.  
  337.     *t = '\0';
  338.   }
  339.   else
  340.   {
  341.     Log ("SkipQuuotes: Expected double-quote in '%s'", *s);
  342.   }
  343. }
  344.  
  345. void RemoveQuotes (char *s)
  346. /*
  347.  *  Remove quotes from string
  348.  */
  349. {
  350.   char *t;
  351.   int i, j, len;
  352.  
  353.   len = strlen (s);
  354.   t = (char *) malloc (len+1);
  355.   strcpy (t, s);
  356.   j = 0;
  357.  
  358.   for (i=0; i<len; i++)
  359.   {
  360.     if (t[i] != '"')
  361.     {
  362.       s[j++] = t[i];
  363.     }
  364.   }
  365.   s[j] = 0;
  366.  
  367.   free (t);
  368. }
  369.  
  370. int Search (struct Tag *tags, char *s)
  371. {
  372.   int i;
  373.  
  374.   SkipSpaces (&s);
  375.  
  376.   for (i=0; tags[i].token != NULL; i++)
  377.   {
  378.     if (!strncasecmp (tags[i].token, s, strlen (tags[i].token)))
  379.     {
  380.       s += strlen (tags[i].token);
  381.       SkipSpaces (&s);
  382.       return (*(tags[i].func))(s);
  383.     }
  384.   }
  385.  
  386.   Log ("Search: Unrecognised token '%s'", s);
  387.   exit (1);
  388.   return 0;
  389. }
  390.  
  391. struct Tag object_tags[] =
  392. {
  393.   {
  394. "name"   , DoACName}
  395.   ,
  396.   {
  397. "data"   , DoData}
  398.   ,
  399.   {
  400. "texture", DoTexture}
  401.   ,
  402.   {
  403. "texrep" , DoTexrep}
  404.   ,
  405.   {
  406. "rot"    , DoRot}
  407.   ,
  408.   {
  409. "loc"    , DoLoc}
  410.   ,
  411.   {
  412. "url"    , DoUrl}
  413.   ,
  414.   {
  415. "numvert", DoNumvert}
  416.   ,
  417.   {
  418. "numsurf", DoNumsurf}
  419.   ,
  420.   {
  421. "kids"   , DoKids}
  422.   ,
  423.   {
  424.     NULL, NULL }
  425. }
  426. ;
  427.  
  428. struct Tag surf_tag[] =
  429. {
  430.   {
  431. "SURF", DoSurf}
  432.   ,
  433.   {
  434.     NULL, NULL}
  435. }
  436. ;
  437.  
  438. struct Tag surface_tags[] =
  439. {
  440.   {
  441. "mat" , DoMat }
  442.   ,
  443.   {
  444. "refs", DoRefs}
  445.   ,
  446.   {
  447.     NULL, NULL}
  448. }
  449. ;
  450.  
  451. struct Tag obj_type_tags[] =
  452. {
  453.   {
  454. "world", DoObjWorld}
  455.   ,
  456.   {
  457. "poly" , DoObjPoly }
  458.   ,
  459.   {
  460. "group", DoObjGroup}
  461.   ,
  462.   {
  463.     NULL, NULL}
  464. }
  465. ;
  466.  
  467. #define OBJ_WORLD  0
  468. #define OBJ_POLY   1
  469. #define OBJ_GROUP  2
  470.  
  471. int DoObjWorld (char *s)
  472. {
  473.   return OBJ_WORLD;
  474. }
  475.  
  476. int DoObjPoly (char *s)
  477. {
  478.   return OBJ_POLY;
  479. }
  480.  
  481. int DoObjGroup (char *s)
  482. {
  483.   return OBJ_GROUP;
  484. }
  485.  
  486. void DoBegin (int flags)
  487. {
  488.   if (last_flags == -1) last_flags = ~flags;
  489.  
  490.   if (((flags>>4) & 0x01) != ((last_flags>>4) & 0x01))
  491.   {
  492.     if ((flags>>4) & 0x01)
  493.     {
  494.       /* Smooth Shaded */
  495.       acsmooth = 1;
  496.     }
  497.     else
  498.     {
  499.       /* Flat Shaded */
  500.       acsmooth = 0;
  501.     }
  502.   }
  503.   /**
  504.  if (((flags>>4) & 0x02) != ((last_flags>>4) & 0x02))
  505.  {
  506.   if ((flags>>4) & 0x02)
  507.   {
  508.    if (acsurfpass == PASS_RENDER) glDisable (GL_CULL_FACE);
  509.   }
  510.   else
  511.   {
  512.    if (acsurfpass == PASS_RENDER) glEnable (GL_CULL_FACE);
  513.   }
  514.  }
  515.  
  516.  if ((last_flags & 0x0F) == 0  && (flags & 0x0F) != 0)
  517.  {
  518.   if (acsurfpass == PASS_RENDER) glDisable (GL_LIGHTING);
  519.  }
  520.  else if ((last_flags & 0x0F) != 0  && (flags & 0x0F) == 0)
  521.  {
  522.   if (acsurfpass == PASS_RENDER) glEnable (GL_LIGHTING);
  523.  }
  524. **/
  525.   last_flags = flags;
  526.  
  527.   switch (flags & 0x0F)
  528.   {
  529.     case 0: if (acsurfpass == PASS_RENDER) glBegin (GL_POLYGON);
  530.     break;
  531.  
  532.     case 1: if (acsurfpass == PASS_RENDER) glBegin (GL_LINE_LOOP);
  533.     break;
  534.  
  535.     case 2: if (acsurfpass == PASS_RENDER) glBegin (GL_LINE_STRIP);
  536.     break;
  537.  
  538.     default:
  539.     Log ("DoBegin: Illegal surface type 0x%02x", flags);
  540.     break;
  541.   }
  542. }
  543.  
  544. int DoMaterial (char *s)
  545. {
  546.   char name[1024], *nm;
  547.   float rgb[3], amb[3], emis[3], spec[3], trans;
  548.   int shi;
  549.  
  550.   if (15 != sscanf (s,
  551.   "%s rgb %f %f %f amb %f %f %f emis %f %f %f spec %f %f %f shi %d trans %f",
  552.   name, &rgb[0], &rgb[1], &rgb[2], &amb[0], &amb[1], &amb[2],
  553.   &emis[0], &emis[1], &emis[2], &spec[0], &spec[1], &spec[2], &shi, &trans))
  554.  {
  555.   Log ("DoMaterial: Can't parse this MATERIAL: %s", s);
  556.  }
  557.  else
  558.  {
  559.   nm = name;
  560.   SkipQuotes (&nm);
  561.  
  562.   /* Get a list for this material */
  563.   matlist[num_materials] = glGenLists (1);
  564.  
  565.   glNewList (matlist[num_materials], GL_COMPILE );
  566.   glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, amb);
  567.   glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, rgb);
  568.   glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec);
  569.   glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, emis);
  570.   glMaterialf  (GL_FRONT_AND_BACK, GL_SHININESS, shi);
  571.   glEndList();
  572.  }
  573.  num_materials++;
  574.  
  575.  return PARSE_CONT;
  576. }
  577.  
  578. int DoObject (char *s)
  579. {
  580.  int i, obj_type, num_kids;
  581.  char buffer[1024];
  582.  
  583.  if (firsttime2)
  584.  {
  585.   glNewList (model[modelnum].list, GL_COMPILE);
  586.   glShadeModel (GL_SMOOTH);
  587.   firsttime2 = 0;
  588.  }
  589.  
  590.  obj_type = Search (obj_type_tags, s);  
  591.  
  592.  switch (obj_type)
  593.  {
  594.  case OBJ_WORLD:
  595.   break;
  596.  
  597.  case OBJ_POLY:
  598.   break;
  599.  
  600.  case OBJ_GROUP:
  601.   break;
  602.  }
  603.  
  604.  need_texture = 0;
  605.  
  606.  glPushMatrix();
  607.  
  608.  while (NULL != fgets (buffer, 1024, acfd))
  609.  {
  610.   if (Search (object_tags, buffer) == PARSE_POP) break;
  611.  }
  612.  
  613.  num_kids = last_num_kids;
  614.  
  615.  for (i=0; i<num_kids; i++)
  616.  {
  617.   fgets (buffer, 1024, acfd);
  618.   Search (top_tags, buffer);
  619.  }
  620.  
  621.  glPopMatrix();
  622.  
  623.  return PARSE_CONT;
  624. }
  625.  
  626. int DoACName (char *s)
  627. {
  628.  SkipQuotes (&s);
  629.  return PARSE_CONT;
  630. }
  631.  
  632. int DoData (char *s)
  633. {
  634.  int i, len;
  635.  
  636.  len = strtol (s, NULL, 0);
  637.  Log ("DoData: WARNING - data string encountered");
  638.  for (i=0; i<len; i++) fgetc (acfd);
  639.  
  640.  return PARSE_CONT;
  641. }
  642.  
  643. int GetTexture (char *s)
  644. {
  645.  int t;
  646.  
  647.  for (t=0; t<ntex; t++)
  648.  {
  649.   if (!strcasecmp (s, tex[t].name)) return t;
  650.  }
  651.  
  652.  return 0;
  653. }
  654.  
  655. int DoTexture (char *s)
  656. {
  657.  static int last_tex = -1;
  658.  int t;
  659.  
  660.  SkipQuotes (&s);
  661.  
  662.  t = GetTexture (s);
  663.  
  664.  if (t != last_tex)
  665.  {
  666.   glBindTexture (GL_TEXTURE_2D, tex[t].id);
  667.  
  668.   last_tex = t;
  669.  }
  670.  
  671.  need_texture = 1;
  672.  
  673.  return PARSE_CONT;
  674. }
  675.  
  676. int DoTexrep (char *s)
  677. {
  678.  float texrep[2];
  679.  
  680.  if (2 != sscanf (s, "%f %f", &texrep[0], &texrep[1]))
  681.   Log ("DoTextrep: Illegal texrep record: %s", s);
  682.  
  683.  return PARSE_CONT;
  684. }
  685.  
  686. int DoRot (char *s)
  687. {
  688.  float mat[4][4];
  689.  
  690.  mat[0][3] = mat[1][3] = mat[2][3] = mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
  691.  mat[3][3] = 1.0f; 
  692.  
  693.  if (9 != sscanf (s, "%f %f %f %f %f %f %f %f %f",
  694.   &mat[0][0], &mat[0][1], &mat[0][2],
  695.   &mat[1][0], &mat[1][1], &mat[1][2],
  696.   &mat[2][0], &mat[2][1], &mat[2][2]))
  697.  {
  698.   Log ("DoRot: Illegal rot record: %s", s);
  699.  }
  700.  
  701.  glMultMatrixf ((float *)mat);
  702.  
  703.  return PARSE_CONT ;
  704. }
  705.  
  706. int DoLoc (char *s)
  707. {
  708.  float loc[3];
  709.  
  710.  if (3 != sscanf (s, "%f %f %f", &loc[0], &loc[1], &loc[2]))
  711.  {
  712.   Log ("DoLoc: Illegal loc record: %s", s);
  713.  }
  714.  
  715.  loc[0] /= 100.0;
  716.  loc[1] /= 100.0;
  717.  loc[2] /= 100.0;
  718.  glTranslatef (loc[0], loc[1], loc[2]);
  719.  
  720.  return PARSE_CONT;
  721. }
  722.  
  723. int DoUrl (char *s)
  724. {
  725.  SkipQuotes (&s);
  726.  return PARSE_CONT;
  727. }
  728.  
  729. int DoNumvert (char *s)
  730. {
  731.  char buffer[1024];
  732.  int i;
  733.  
  734.  nv = strtol (s, NULL, 0);
  735.  
  736.  if (vtab != NULL) free (vtab) ;
  737.  
  738.  vtab = (struct ACVertex *) malloc (3*nv*sizeof(struct ACVertex));
  739.  
  740.  for (i=0; i<nv; i++)
  741.  {
  742.   fgets (buffer, 1024, acfd);
  743.  
  744.   if (3 != sscanf (buffer, "%f %f %f", &vtab[i].v[0], &vtab[i].v[1], &vtab[i].v[2]))
  745.   {
  746.    Log ("DoNumvert: Illegal vertex record: %s", buffer);
  747.   }
  748.   vtab[i].v[0] /= 100.0;
  749.   vtab[i].v[1] /= 100.0;
  750.   vtab[i].v[2] /= 100.0;
  751.  
  752.   vtab[i].normal[0] = vtab[i].normal[1] = vtab[i].normal[2] = 0.0;
  753.   vtab[i].n = 0.0;
  754.  
  755.   if (vtab[i].v[0] < model[modelnum].lobound[0]) model[modelnum].lobound[0] = vtab[i].v[0];
  756.   if (vtab[i].v[1] < model[modelnum].lobound[1]) model[modelnum].lobound[1] = vtab[i].v[1];
  757.   if (vtab[i].v[2] < model[modelnum].lobound[2]) model[modelnum].lobound[2] = vtab[i].v[2];
  758.   if (vtab[i].v[0] > model[modelnum].hibound[0]) model[modelnum].hibound[0] = vtab[i].v[0];
  759.   if (vtab[i].v[1] > model[modelnum].hibound[1]) model[modelnum].hibound[1] = vtab[i].v[1];
  760.   if (vtab[i].v[2] > model[modelnum].hibound[2]) model[modelnum].hibound[2] = vtab[i].v[2];
  761.  }
  762.  
  763.  return PARSE_CONT;
  764. }
  765.  
  766. int DoNumsurf (char *s)
  767. {
  768.  int i, ns, v;
  769.  long pos, p;
  770.  char buffer[1024];
  771.  
  772.  ns = strtol (s, NULL, 0);
  773.  
  774.  /* Do first pass to average normals */
  775.  pos = ftell (acfd);
  776.  acsurfpass = PASS_NORMAL;
  777.  for (i=0; i<ns; i++)
  778.  {
  779.   p = ftell (acfd);
  780.   fgets (buffer, 1024, acfd);
  781.   Search (surf_tag, buffer);
  782.  }
  783.  
  784.  /* Back to beginning of object */
  785.  fseek (acfd, pos, SEEK_SET);
  786.  
  787.  /* Average normals */
  788.  for (v=0; v<nv; v++)
  789.  {
  790.   vtab[v].normal[0] /= vtab[v].n;
  791.   vtab[v].normal[1] /= vtab[v].n;
  792.   vtab[v].normal[2] /= vtab[v].n;
  793.  }
  794.  
  795.  /* Now render */
  796.  acsurfpass = PASS_RENDER;
  797.  last_mat = (-1);
  798.  
  799.  for (i=0; i<ns; i++)
  800.  {
  801.   p = ftell (acfd);
  802.   fgets (buffer, 1024, acfd);
  803.   Search (surf_tag, buffer);
  804.  }
  805.  
  806.  return PARSE_CONT;
  807. }
  808.  
  809. int DoSurf (char *s)
  810. {
  811.  char buffer[1024];
  812.  
  813.  current_flags = strtol (s, NULL, 0);
  814.  
  815.  while (NULL != fgets (buffer, 1024, acfd))
  816.  {
  817.   if (Search (surface_tags, buffer) == PARSE_POP) break;
  818.  }
  819.  
  820.  return PARSE_CONT ;
  821. }
  822.  
  823. int DoMat (char *s)
  824. {
  825.  int mat;
  826.  
  827.  mat = strtol (s, NULL, 0);
  828.  
  829.  if (mat != last_mat)
  830.  {
  831.   if (acsurfpass == PASS_RENDER) glCallList (matlist[mat]);
  832.   last_mat = mat;
  833.  }
  834.  
  835.  return PARSE_CONT ;
  836. }
  837.  
  838. int DoRefs (char *s)
  839. {
  840.  int i;
  841.  int nrefs;
  842.  char buffer[1024] ;
  843.  int *vlist;
  844.  float *tlistu, *tlistv, nrm[3];
  845.  
  846.  nrefs = strtol (s, NULL, 0);
  847.  
  848.  if (nrefs == 0) return PARSE_POP;
  849.  
  850.  if (need_texture && !texture_enabled)
  851.  {
  852.   if (acsurfpass == PASS_RENDER) glEnable (GL_TEXTURE_2D);
  853.   texture_enabled = 1;
  854.  }
  855.  else if (!need_texture && texture_enabled)
  856.  {
  857.   if (acsurfpass == PASS_RENDER) glDisable (GL_TEXTURE_2D);
  858.   texture_enabled = 0;
  859.  }
  860.  
  861.  vlist  = (int *) malloc (sizeof(int)*nrefs);
  862.  tlistu = (float *) malloc (sizeof(float)*nrefs) ;
  863.  tlistv = (float *) malloc (sizeof(float)*nrefs) ;
  864.  
  865.  DoBegin (current_flags);
  866.  
  867.  for (i=0; i<nrefs; i++)
  868.  {
  869.   fgets (buffer, 1024, acfd);
  870.  
  871.   if (3 != sscanf (buffer, "%d %f %f", &vlist[i], &tlistu[i], &tlistv[i]))
  872.   {
  873.    Log ("DoRefs: Illegal ref record: %s", buffer);
  874.    exit (1);
  875.   }
  876.  }
  877.  
  878.  if (nrefs >= 3)
  879.  {
  880.   MakeNormal (nrm, vtab[vlist[0]].v, vtab[vlist[1]].v, vtab[vlist[2]].v);
  881.  
  882.   if (!acsmooth && (acsurfpass == PASS_RENDER))
  883.   {
  884.    glNormal3fv (nrm);
  885.   }
  886.  }
  887.  
  888.  for (i=0; i<nrefs; i++)
  889.  {
  890.   /* Maintain normal first pass */
  891.   if (acsmooth && (acsurfpass == PASS_NORMAL))
  892.   {
  893.    MaintainNormal (vlist[i], nrm);
  894.   }
  895.  
  896.   /* Render second pass */
  897.   if (acsmooth && (acsurfpass == PASS_RENDER))
  898.   {
  899.    glNormal3fv (vtab[vlist[i]].normal);
  900.   }
  901.  
  902.   if (acsurfpass == PASS_RENDER)
  903.   {
  904.    glTexCoord2f (tlistu[i], tlistv[i]);
  905.    glVertex3fv (vtab[vlist[i]].v);
  906.   }
  907.  }
  908.  
  909.  free (vlist);
  910.  free (tlistu);
  911.  free (tlistv);
  912.  
  913.  if (acsurfpass == PASS_RENDER) glEnd();
  914.  
  915.  return PARSE_POP;
  916. }
  917.  
  918. int DoKids (char *s)
  919. {
  920.  last_num_kids = strtol (s, NULL, 0);
  921.  return PARSE_POP;
  922. }
  923.  
  924. void MaintainNormal (int i, float *n)
  925. /*
  926.  *  Maintain a vertex normal
  927.  */
  928. {
  929.  vtab[i].n += 1.0;
  930.  
  931.  vtab[i].normal[0] += n[0];
  932.  vtab[i].normal[1] += n[1];
  933.  vtab[i].normal[2] += n[2];
  934. }
  935.  
  936. /** ------------- The rest loads SGI texture files --------------- **/
  937.  
  938. /* Some magic constants in the file header. */
  939.  
  940. #define SGI_IMG_MAGIC           0x01DA
  941. #define SGI_IMG_SWABBED_MAGIC   0xDA01   /* This is how it appears on a PC */
  942. #define SGI_IMG_VERBATIM        0
  943. #define SGI_IMG_RLE             1
  944.  
  945. static int            sgi_max ;
  946. static int            sgi_min ;
  947. static int            sgi_colormap ;
  948. static unsigned short sgi_magic ;
  949. static char           sgi_type ;
  950. static char           sgi_bpp ;
  951. static unsigned int  *sgi_start ;
  952. static int           *sgi_leng ;
  953. static unsigned char *sgi_temp ;
  954. static int            sgi_swapped ;
  955. static FILE          *sgi_fd ;
  956. static unsigned short sgi_dim ;
  957. static unsigned short sgi_xsize ;
  958. static unsigned short sgi_ysize ;
  959. static unsigned short sgi_zsize ;
  960.  
  961. static void makeConsistentHeader ()
  962. {
  963.   /*
  964.     Sanity checks - and a workaround for buggy RGB files generated by
  965.     the MultiGen Paint program because it will sometimes get confused
  966.     about the way to represent maps with more than one component.
  967.  
  968.     eg   Y > 1, Number of dimensions == 1
  969.          Z > 1, Number of dimensions == 2
  970.   */
  971.  
  972.   if ( sgi_ysize > 1 && sgi_dim < 2 ) sgi_dim = 2 ;
  973.   if ( sgi_zsize > 1 && sgi_dim < 3 ) sgi_dim = 3 ;
  974.   if ( sgi_dim < 1 ) sgi_ysize = 1 ;
  975.   if ( sgi_dim < 2 ) sgi_zsize = 1 ;
  976.   if ( sgi_dim > 3 ) sgi_dim   = 3 ;
  977.   if ( sgi_zsize < 1 && sgi_ysize == 1 ) sgi_dim = 1 ;
  978.   if ( sgi_zsize < 1 && sgi_ysize != 1 ) sgi_dim = 2 ;
  979.   if ( sgi_zsize >= 1 ) sgi_dim = 3 ;
  980.  
  981.   /*
  982.     A very few SGI image files have 2 bytes per component - this
  983.     tool cannot deal with those kinds of files. 
  984.   */
  985.  
  986.   if ( sgi_bpp == 2 )
  987.   {
  988.     Log ("makeConsistentHeader: Can't work with SGI images with %d bpp", sgi_bpp);
  989.     exit (1);
  990.   }
  991.  
  992.   sgi_bpp = 1 ;
  993.   sgi_min = 0 ;
  994.   sgi_max = 255 ;
  995.   sgi_magic = SGI_IMG_MAGIC ;
  996.   sgi_colormap = 0 ;
  997. }
  998.  
  999. static void swab_short ( unsigned short *x )
  1000. {
  1001.   if ( sgi_swapped )
  1002.     *x = (( *x >>  8 ) & 0x00FF ) | 
  1003.          (( *x <<  8 ) & 0xFF00 ) ;
  1004. }
  1005.  
  1006. static void swab_int ( unsigned int *x )
  1007. {
  1008.   if ( sgi_swapped )
  1009.     *x = (( *x >> 24 ) & 0x000000FF ) | 
  1010.          (( *x >>  8 ) & 0x0000FF00 ) | 
  1011.          (( *x <<  8 ) & 0x00FF0000 ) | 
  1012.          (( *x << 24 ) & 0xFF000000 ) ;
  1013. }
  1014.  
  1015. static void swab_int_array ( int *x, int leng )
  1016. {
  1017.   int i;
  1018.  
  1019.   if ( ! sgi_swapped )
  1020.     return ;
  1021.  
  1022.   for ( i = 0 ; i < leng ; i++ )
  1023.   {
  1024.     *x = (( *x >> 24 ) & 0x000000FF ) | 
  1025.          (( *x >>  8 ) & 0x0000FF00 ) | 
  1026.          (( *x <<  8 ) & 0x00FF0000 ) | 
  1027.          (( *x << 24 ) & 0xFF000000 ) ;
  1028.     x++ ;
  1029.   }
  1030. }
  1031.  
  1032.  
  1033. static unsigned char readByte ()
  1034. {
  1035.   unsigned char x ;
  1036.   fread ( & x, sizeof(unsigned char), 1, sgi_fd ) ;
  1037.   return x ;
  1038. }
  1039.  
  1040. static unsigned short readShort ()
  1041. {
  1042.   unsigned short x ;
  1043.   fread ( & x, sizeof(unsigned short), 1, sgi_fd ) ;
  1044.   swab_short ( & x ) ;
  1045.   return x ;
  1046. }
  1047.  
  1048. static unsigned int readInt ()
  1049. {
  1050.   unsigned int x ;
  1051.   fread ( & x, sizeof(unsigned int), 1, sgi_fd ) ;
  1052.   swab_int ( & x ) ;
  1053.   return x ;
  1054. }
  1055.  
  1056.  
  1057. static void getRow ( unsigned char *buf, int y, int z )
  1058. {
  1059.     unsigned char pixel, count ;
  1060.  
  1061.   if ( y >= sgi_ysize ) y = sgi_ysize - 1 ;
  1062.   if ( z >= sgi_zsize ) z = sgi_zsize - 1 ;
  1063.  
  1064.   fseek ( sgi_fd, sgi_start [ z * sgi_ysize + y ], SEEK_SET ) ;
  1065.  
  1066.   if ( sgi_type == SGI_IMG_RLE )
  1067.   {
  1068.     unsigned char *tmpp = sgi_temp ;
  1069.     unsigned char *bufp = buf ;
  1070.  
  1071.     fread ( sgi_temp, 1, sgi_leng [ z * sgi_ysize + y ], sgi_fd ) ;
  1072.  
  1073.     while ( 1 )
  1074.     {
  1075.       pixel = *tmpp++ ;
  1076.  
  1077.       count = ( pixel & 0x7f ) ;
  1078.  
  1079.       if ( count == 0 )
  1080.  break ;
  1081.  
  1082.       if ( pixel & 0x80 )
  1083.       {
  1084.         while ( count-- )
  1085.    *bufp++ = *tmpp++ ;
  1086.       }
  1087.       else
  1088.       {
  1089.         pixel = *tmpp++ ;
  1090.  
  1091.  while ( count-- )
  1092.           *bufp++ = pixel ;
  1093.       }
  1094.     }
  1095.   }
  1096.   else
  1097.     fread ( buf, 1, sgi_xsize, sgi_fd ) ;
  1098. }
  1099.  
  1100.  
  1101. static void getPlane ( unsigned char *buf, int z )
  1102. {
  1103.   int y;
  1104.   if ( sgi_fd == NULL )
  1105.     return ;
  1106.  
  1107.   if ( z >= sgi_zsize ) z = sgi_zsize - 1 ;
  1108.  
  1109.   for ( y = 0 ; y < sgi_ysize ; y++ )
  1110.     getRow ( & buf [ y * sgi_xsize ], y, z ) ;
  1111. }
  1112.  
  1113.  
  1114.  
  1115. static void getImage ( unsigned char *buf )
  1116. {
  1117.   int y, z;
  1118.  
  1119.   if ( sgi_fd == NULL )
  1120.     return ;
  1121.  
  1122.   for (y = 0 ; y < sgi_ysize ; y++ )
  1123.     for (z = 0 ; z < sgi_zsize ; z++ )
  1124.       getRow ( & buf [ ( z * sgi_ysize + y ) * sgi_xsize ], y, z ) ;
  1125. }
  1126.  
  1127. void load_sgi_texture ( char *fname )
  1128. {
  1129.   int i, tablen, x, y, l, maxlen;
  1130.   GLubyte *texels [ 20 ], *ptr ;
  1131.   unsigned char *rbuf, *gbuf, *bbuf, *abuf;
  1132.   int lev, map_level;
  1133.   int j, x2, y2, c;
  1134.  
  1135.   sgi_dim   = 0 ;
  1136.   sgi_start = NULL ;
  1137.   sgi_leng  = NULL ;
  1138.   sgi_temp  = NULL ;
  1139.  
  1140.   sgi_swapped = 0 ;
  1141.  
  1142.   sgi_fd = fopen ( fname, "rb" ) ;
  1143.  
  1144.   if ( sgi_fd == NULL )
  1145.   {
  1146.     Log ("load_sgi_texture: Failed to open '%s' for reading.", fname ) ;
  1147.     return ;
  1148.   }
  1149.  
  1150.   sgi_magic = readShort () ;
  1151.  
  1152.   if ( sgi_magic != SGI_IMG_MAGIC && sgi_magic != SGI_IMG_SWABBED_MAGIC )
  1153.   {
  1154.     Log ("load_sgi_texture: %s: Unrecognised magic number 0x%04x", fname, sgi_magic ) ;
  1155.     exit ( 1 ) ;
  1156.   }
  1157.  
  1158.   if ( sgi_magic == SGI_IMG_SWABBED_MAGIC )
  1159.   {
  1160.     sgi_swapped = 1 ;
  1161.     swab_short ( & sgi_magic ) ;
  1162.   }
  1163.  
  1164.   sgi_type  = readByte  () ;
  1165.   sgi_bpp   = readByte  () ;
  1166.   sgi_dim   = readShort () ;
  1167.  
  1168.   /*
  1169.     This is a backstop test - if for some reason the magic number isn't swabbed, this
  1170.     test will still catch a swabbed file. Of course images with more than 256 dimensions
  1171.     are not catered for :-)
  1172.   */
  1173.  
  1174.   if ( sgi_dim > 255 )
  1175.   {
  1176.     Log ("load_sgi_texture: %s: Bad swabbing?!?", fname ) ;
  1177.     sgi_swapped = ! sgi_swapped ;
  1178.     swab_short ( & sgi_dim ) ;
  1179.     sgi_magic = SGI_IMG_MAGIC ;
  1180.   }
  1181.  
  1182.   sgi_xsize = readShort () ;
  1183.   sgi_ysize = readShort () ;
  1184.   sgi_zsize = readShort () ;
  1185.   sgi_min   = readInt   () ;  
  1186.   sgi_max   = readInt   () ;  
  1187.               readInt   () ;  /* Dummy field */
  1188.  
  1189.   for (i = 0 ; i < 80 ; i++ )
  1190.     readByte () ;         /* Name field */
  1191.  
  1192.   sgi_colormap = readInt () ;
  1193.  
  1194.   for (i = 0 ; i < 404 ; i++ )
  1195.     readByte () ;         /* Dummy field */
  1196.  
  1197.   makeConsistentHeader () ;
  1198.  
  1199.   tablen = sgi_ysize * sgi_zsize ;
  1200.   sgi_start = (unsigned int *) malloc (tablen*sizeof(unsigned int)) ;
  1201.   sgi_leng  = (int *) malloc (sizeof(int)*tablen) ;
  1202.  
  1203.   if ( sgi_type == SGI_IMG_RLE )
  1204.   {
  1205.     fread ( sgi_start, sizeof ( unsigned int ), tablen, sgi_fd ) ;
  1206.     fread ( sgi_leng , sizeof (  int ), tablen, sgi_fd ) ;
  1207.     swab_int_array ( (int *) sgi_start, tablen ) ;
  1208.     swab_int_array ( (int *) sgi_leng , tablen ) ;
  1209.  
  1210.     maxlen = 0 ;
  1211.  
  1212.     for (i = 0 ; i < tablen ; i++ )
  1213.       if ( sgi_leng [ i ] > maxlen )
  1214.         maxlen = sgi_leng [ i ] ;
  1215.  
  1216.     sgi_temp = (unsigned char *) malloc (maxlen) ;
  1217.   }
  1218.   else
  1219.   {
  1220.     sgi_temp = NULL ;
  1221.  
  1222.     for (i = 0 ; i < sgi_zsize ; i++ )
  1223.       for (j = 0 ; j < sgi_ysize ; j++ )
  1224.       {
  1225.         sgi_start [ i * sgi_ysize + j ] = sgi_xsize * ( i * sgi_ysize + j ) + 512 ;
  1226.         sgi_leng  [ i * sgi_ysize + j ] = sgi_xsize ;
  1227.       }
  1228.   }
  1229.  
  1230.   if ( sgi_zsize <= 0 || sgi_zsize > 4 )
  1231.   {
  1232.     Log ("load_sgi_texture: %s: Not an int/inta/rgb/rgba image?!?", fname ) ;
  1233.     exit ( 1 ) ;
  1234.   }
  1235.  
  1236.  
  1237.   for (i = 0 ; i < 20 ; i++ )
  1238.     texels [ 0 ] = NULL ;
  1239.  
  1240.   texels [ 0 ] = (GLubyte *) malloc (sizeof(GLubyte)* sgi_xsize * sgi_ysize * sgi_zsize ) ;
  1241.  
  1242.   ptr = texels [ 0 ] ;
  1243.  
  1244.   rbuf = malloc (sgi_xsize);
  1245.   gbuf = (sgi_zsize>1) ? malloc(sgi_xsize): (unsigned char *) NULL ;
  1246.   bbuf = (sgi_zsize>2) ? malloc(sgi_xsize): (unsigned char *) NULL ;
  1247.   abuf = (sgi_zsize>3) ? malloc(sgi_xsize): (unsigned char *) NULL ;
  1248.  
  1249.   for ( y = 0 ; y < sgi_ysize ; y++ )
  1250.   {
  1251.     switch ( sgi_zsize )
  1252.     {
  1253.       case 1 :
  1254.  getRow ( rbuf, y, 0 ) ;
  1255.  
  1256.  for ( x = 0 ; x < sgi_xsize ; x++ )
  1257.    *ptr++ = rbuf [ x ] ;
  1258.  
  1259.  break ;
  1260.  
  1261.       case 2 :
  1262.  getRow ( rbuf, y, 0 ) ;
  1263.  getRow ( gbuf, y, 1 ) ;
  1264.  
  1265.  for (x = 0 ; x < sgi_xsize ; x++ )
  1266.  {
  1267.    *ptr++ = rbuf [ x ] ;
  1268.    *ptr++ = gbuf [ x ] ;
  1269.  }
  1270.  break ;
  1271.  
  1272.       case 3 :
  1273.         getRow ( rbuf, y, 0 ) ;
  1274.  getRow ( gbuf, y, 1 ) ;
  1275.  getRow ( bbuf, y, 2 ) ;
  1276.  
  1277.  for (x = 0 ; x < sgi_xsize ; x++ )
  1278.  {
  1279.    *ptr++ = rbuf [ x ] ;
  1280.    *ptr++ = gbuf [ x ] ;
  1281.    *ptr++ = bbuf [ x ] ;
  1282.  }
  1283.  break ;
  1284.  
  1285.       case 4 :
  1286.         getRow ( rbuf, y, 0 ) ;
  1287.  getRow ( gbuf, y, 1 ) ;
  1288.  getRow ( bbuf, y, 2 ) ;
  1289.  getRow ( abuf, y, 3 ) ;
  1290.  
  1291.  for (x = 0 ; x < sgi_xsize ; x++ )
  1292.  {
  1293.    *ptr++ = rbuf [ x ] ;
  1294.    *ptr++ = gbuf [ x ] ;
  1295.    *ptr++ = bbuf [ x ] ;
  1296.    *ptr++ = abuf [ x ] ;
  1297.  }
  1298.  break ;
  1299.     }
  1300.   }
  1301.  
  1302.   for ( lev = 0 ; (( sgi_xsize >> (lev+1) ) != 0 ||
  1303.                    ( sgi_ysize >> (lev+1) ) != 0 ) ; lev++ )
  1304.   {
  1305.     /* Suffix '1' is the higher level map, suffix '2' is the lower level. */
  1306.  
  1307.     int l1 =  lev  ;
  1308.     int l2 = lev+1 ;
  1309.     int w1 = sgi_xsize >> l1 ;
  1310.     int h1 = sgi_ysize >> l1 ;
  1311.     int w2 = sgi_xsize >> l2 ;
  1312.     int h2 = sgi_ysize >> l2 ;
  1313.  
  1314.     if ( w1 <= 0 ) w1 = 1 ;
  1315.     if ( h1 <= 0 ) h1 = 1 ;
  1316.     if ( w2 <= 0 ) w2 = 1 ;
  1317.     if ( h2 <= 0 ) h2 = 1 ;
  1318.  
  1319.     texels[l2] = (GLubyte *) malloc (sizeof(GLubyte)*  w2 * h2 * sgi_zsize ) ;
  1320.  
  1321.     for (x2 = 0 ; x2 < w2 ; x2++ )
  1322.       for (y2 = 0 ; y2 < h2 ; y2++ )
  1323.         for (c = 0 ; c < sgi_zsize ; c++ )
  1324.         {
  1325.           int x1   = x2 + x2 ;
  1326.           int x1_1 = ( x1 + 1 ) % w1 ;
  1327.           int y1   = y2 + y2 ;
  1328.           int y1_1 = ( y1 + 1 ) % h1 ;
  1329.  
  1330.    int t1 = texels [ l1 ] [ (y1   * w1 + x1  ) * sgi_zsize + c ] ;
  1331.    int t2 = texels [ l1 ] [ (y1_1 * w1 + x1  ) * sgi_zsize + c ] ;
  1332.    int t3 = texels [ l1 ] [ (y1   * w1 + x1_1) * sgi_zsize + c ] ;
  1333.    int t4 = texels [ l1 ] [ (y1_1 * w1 + x1_1) * sgi_zsize + c ] ;
  1334.  
  1335.           texels [ l2 ] [ (y2 * w2 + x2) * sgi_zsize + c ] =
  1336.                                            ( t1 + t2 + t3 + t4 ) / 4 ;
  1337.         }
  1338.   }
  1339.  
  1340.   texels [ lev+1 ] = NULL ;
  1341.  
  1342.   if (rbuf != NULL) free (rbuf)  ;
  1343.   if (gbuf != NULL) free (gbuf)  ;
  1344.   if (bbuf != NULL) free (bbuf)  ;
  1345.   if (abuf != NULL) free (abuf)  ;
  1346.  
  1347.   if ( ! ((sgi_xsize & (sgi_xsize-1))==0) ||
  1348.        ! ((sgi_ysize & (sgi_ysize-1))==0) )
  1349.   {
  1350.     Log ("load_sgi_texture: %s: Map is not a power-of-two in size!", fname ) ;
  1351.     exit ( 1 ) ;
  1352.   }
  1353.  
  1354.   glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ) ;
  1355.  
  1356.   map_level = 0 ;
  1357.  
  1358.   if ( sgi_xsize > 256 || sgi_ysize > 256 )
  1359.   {
  1360.     while ( sgi_xsize > 256 || sgi_ysize > 256 )
  1361.     {
  1362.       if (texels[0] != NULL) free (texels[0]) ;
  1363.       sgi_xsize >>= 1 ;
  1364.       sgi_ysize >>= 1 ;
  1365.  
  1366.       for (l = 0 ; texels [ l ] != NULL ; l++ )
  1367.  texels [ l ] = texels [ l+1 ] ;
  1368.     }
  1369.   }
  1370.  
  1371.   for (i = 0 ; texels [ i ] != NULL ; i++ )
  1372.   {
  1373.     int w = sgi_xsize>>i ;
  1374.     int h = sgi_ysize>>i ;
  1375.  
  1376.     if ( w <= 0 ) w = 1 ;
  1377.     if ( h <= 0 ) h = 1 ;
  1378.  
  1379.     glTexImage2D  ( GL_TEXTURE_2D,
  1380.                      map_level, sgi_zsize, w, h, 0 /* Border */,
  1381.                             (sgi_zsize==1)?GL_LUMINANCE:
  1382.                             (sgi_zsize==2)?GL_LUMINANCE_ALPHA:
  1383.                             (sgi_zsize==3)?GL_RGB:
  1384.                                            GL_RGBA,
  1385.                             GL_UNSIGNED_BYTE, (GLvoid *) texels[i] ) ;
  1386.     map_level++ ;
  1387.   }
  1388.  
  1389.   fclose (sgi_fd);
  1390. }
  1391.